package splug.cjk;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import splug.cjk.packet.BBSCarPoolPacket;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

public class FindCarPool extends MapActivity implements LocationListener{

	//위치정보, 위도, 경도에 대한 속성
	private LocationManager _Location;
	private double _Latitude;
	private double _Longitude;

	//지도 출력을 위한 속성
	private MapView map;
	private MapController controller;

	//다이얼로그 출력을 위한 속성
	private AlertDialog.Builder alertDialog;

	//게시판 검색을 위한 버튼
	private Button btn_tab1_find; //태워드립니다 검색
	private Button btn_tab2_find; //태워주세요 검색
	private Button btn_option; //검색옵션

	//검색중일 때 메시지를 나타내기 위한 텍스트뷰
	private TextView text_progress;

	//검색결과를 가지고 있을 리스트
	private ArrayList<Content> content = new ArrayList<Content>();
	private ArrayList<BBSCarPoolContent> sub_content = new ArrayList<BBSCarPoolContent>();
	private ArrayList<Content> result_content = new ArrayList<Content>();
	private ArrayList<BBSCarPoolContent> result_sub_content = new ArrayList<BBSCarPoolContent>();

	private String id;

	/*
	 * 검색옵션 기본 10km
	 * flag == 0 : 반경 2km
	 * flag == 1 : 반경 5km
	 * flag == 2 : 반경 10km
	 * flag == 3 : 반경 20km
	 * flag == 4 : 반경 50km
	 */
	private int flag = 2;


	/**
	 * 메인 메소드
	 */
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.findcarpool);

		Bundle b = this.getIntent().getExtras();
		id = b.getString("ID");

		//텍스트뷰의 리소스를 가져온다
		text_progress = (TextView) findViewById(R.id.text_search_progress);

		//버튼의 리소스를 가져온다
		btn_tab1_find = (Button) findViewById(R.id.btn_map_tab1);
		btn_tab2_find = (Button) findViewById(R.id.btn_map_tab2);
		btn_option = (Button) findViewById(R.id.btn_carpool_option);

		//버튼에 리스너를 추가한다
		btn_tab1_find.setOnClickListener(on_tab1);
		btn_tab2_find.setOnClickListener(on_tab2);
		btn_option.setOnClickListener(on_option);

		//맵의 리소스를 가져온다
		map = (MapView) findViewById(R.id.mapview);
		controller = map.getController();
		controller.setZoom(12);		

		/*
		 * 위성지도 off
		 * zoom 컨트롤 on
		 */
		map.setSatellite(false);
		map.setBuiltInZoomControls(true);

		/*
		 * BestProvider를 찾아서 불러온다
		 */
		_Location = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Criteria _Criteria = new Criteria();
		_Criteria.setAccuracy(Criteria.NO_REQUIREMENT);
		_Criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
		_Criteria.setAltitudeRequired(false);
		String _BestProvider = _Location.getBestProvider(_Criteria, true);

		//위치정보가 변경되었을 때 알려주는 업데이트 메소드(10미터 벗어났을때, 10초마다 체크)
		_Location.requestLocationUpdates(_BestProvider, 10000, 10, FindCarPool.this);
	}

	/**
	 * 태워드립니다 버튼이 눌렸을 때 이벤트
	 */
	private View.OnClickListener on_tab1 = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			//이전의 검색결과는 초기화 한다
			result_content.clear();
			result_sub_content.clear();

			//검색중이라고 알림
			text_progress.setText("검색중...");

			/*
			 * 태워드립니다 게시판의 게시물을 모두 불러온다
			 */
			try {
				Socket socket = new Socket(LetsGoActivity.server_ip, 2007);

				InputStream is = socket.getInputStream();
				OutputStream os = socket.getOutputStream();

				OutputStreamWriter osw = new OutputStreamWriter(os);
				InputStreamReader isr = new InputStreamReader(is);

				osw.write('5');
				osw.flush();

				int ack = isr.read();

				if(ack == '1'){
					ObjectInputStream input = new ObjectInputStream(is);
					BBSCarPoolPacket packet = (BBSCarPoolPacket) input.readObject();

					content = packet.getContent();
					sub_content = packet.getSub_content();
				}
				else{
					Toast.makeText(FindCarPool.this, "네트워크 연결상대가 좋지 않습니다", Toast.LENGTH_SHORT).show();
				}


			} catch (Exception e) {
				Toast.makeText(FindCarPool.this, "네트워크 연결상대가 좋지 않습니다", Toast.LENGTH_SHORT).show();
			}

			/*
			 * 게시물의 출발지의 위도와 경도를 추출하여 거리를 계산한다 
			 */
			double distance = 0;
			for(int i = 0; i < sub_content.size(); i++){
				//내 위치의 위도와 경도를 입력한다
				Location locationMe = new Location("A");
				locationMe.setLatitude(_Latitude);
				locationMe.setLongitude(_Longitude);

				//게시물의 위도와 경도를 입력한다.
				Location locationYou = new Location("B");
				locationYou.setLatitude(sub_content.get(i).getLatitude());
				locationYou.setLongitude(sub_content.get(i).getLongitude());

				//직선거리를 환산한다(단위 : 미터)
				distance = locationMe.distanceTo(locationYou);

				//flag의 값에 따라서 범위를 다르게 설정한다
				double range = 0.0;
				switch(flag){
				case 0:
					range = 2000.0;
					break;
				case 1:
					range = 5000.0;
					break;
				case 2:
					range = 10000.0;
					break;
				case 3:
					range = 20000.0;
					break;
				case 4:
					range = 50000.0;
					break;
				}
				if (distance < range){
					Content c = new Content(content.get(i).getTitle(), content.get(i).getId());
					result_content.add(c);

					BBSCarPoolContent b = new BBSCarPoolContent(sub_content.get(i).getNumber(), sub_content.get(i).getStart(), sub_content.get(i).getFinish(), 
							sub_content.get(i).getTime(), sub_content.get(i).getContent(), sub_content.get(i).getDate(), sub_content.get(i).getLatitude(), sub_content.get(i).getLongitude());
					result_sub_content.add(b);
				}
			}

			//검색결과를 이미지로 띄운다
			Drawable marker = getResources().getDrawable(R.drawable.find);
			marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
			map.getOverlays().clear();
			map.getOverlays().add(new SitesOverlay(marker));

			map.postInvalidate();

			//검색이 완료되었음을 알림
			switch(flag){
			case 0:
				text_progress.setText("내 주변 2km 이내 검색완료");
				break;
			case 1:
				text_progress.setText("내 주변 5km 이내 검색완료");
				break;
			case 2:
				text_progress.setText("내 주변 10km 이내 검색완료");
				break;
			case 3:
				text_progress.setText("내 주변 20km 이내 검색완료");
				break;
			case 4:
				text_progress.setText("내 주변 50km 이내 검색완료");
				break;
			}
			Toast.makeText(FindCarPool.this, "검색완료. find 이미지를 클릭하면 자세한 내용을 볼 수 있습니다.", Toast.LENGTH_SHORT).show();
		}
	};

	/**
	 * 태워주세요 버튼이 눌렸을 때 이벤트
	 */
	private View.OnClickListener on_tab2 = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			//이전의 검색결과는 초기화 한다
			result_content.clear();
			result_sub_content.clear();

			//검색중이라고 알림
			text_progress.setText("검색중...");

			/*
			 * 태워주세요 게시판의 게시물을 모두 불러온다
			 */
			try {
				Socket socket = new Socket(LetsGoActivity.server_ip, 2007);

				InputStream is = socket.getInputStream();
				OutputStream os = socket.getOutputStream();

				OutputStreamWriter osw = new OutputStreamWriter(os);
				InputStreamReader isr = new InputStreamReader(is);

				osw.write('7');
				osw.flush();

				int ack = isr.read();

				if(ack == '1'){
					ObjectInputStream input = new ObjectInputStream(is);
					BBSCarPoolPacket packet = (BBSCarPoolPacket) input.readObject();

					content = packet.getContent();
					sub_content = packet.getSub_content();
				}
				else{
					Toast.makeText(FindCarPool.this, "네트워크 연결상대가 좋지 않습니다", Toast.LENGTH_SHORT).show();
				}


			} catch (Exception e) {
				Toast.makeText(FindCarPool.this, "네트워크 연결상대가 좋지 않습니다", Toast.LENGTH_SHORT).show();
			}

			/*
			 * 게시물의 출발지의 위도와 경도를 추출하여 거리를 계산한다 
			 */
			double distance = 0;
			for(int i = 0; i < sub_content.size(); i++){
				//내 위치의 위도와 경도를 입력한다
				Location locationMe = new Location("A");
				locationMe.setLatitude(_Latitude);
				locationMe.setLongitude(_Longitude);

				//게시물의 위도와 경도를 입력한다.
				Location locationYou = new Location("B");
				locationYou.setLatitude(sub_content.get(i).getLatitude());
				locationYou.setLongitude(sub_content.get(i).getLongitude());

				//직선거리를 환산한다(단위 : 미터)
				distance = locationMe.distanceTo(locationYou);

				//flag의 값에 따라서 범위를 다르게 설정한다
				double range = 0.0;
				switch(flag){
				case 0:
					range = 2000.0;
					break;
				case 1:
					range = 5000.0;
					break;
				case 2:
					range = 10000.0;
					break;
				case 3:
					range = 20000.0;
					break;
				case 4:
					range = 50000.0;
					break;
				}
				if (distance < range){
					Content c = new Content(content.get(i).getTitle(), content.get(i).getId());
					result_content.add(c);

					BBSCarPoolContent b = new BBSCarPoolContent(sub_content.get(i).getNumber(), sub_content.get(i).getStart(), sub_content.get(i).getFinish(), 
							sub_content.get(i).getTime(), sub_content.get(i).getContent(), sub_content.get(i).getDate(), sub_content.get(i).getLatitude(), sub_content.get(i).getLongitude());
					result_sub_content.add(b);
				}
			}

			//검색결과를 이미지로 띄운다
			Drawable marker = getResources().getDrawable(R.drawable.find);
			marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
			map.getOverlays().clear();
			map.getOverlays().add(new SitesOverlay(marker));

			map.postInvalidate();

			//검색이 완료되었음을 알림
			switch(flag){
			case 0:
				text_progress.setText("내 주변 2km 이내 검색완료");
				break;
			case 1:
				text_progress.setText("내 주변 5km 이내 검색완료");
				break;
			case 2:
				text_progress.setText("내 주변 10km 이내 검색완료");
				break;
			case 3:
				text_progress.setText("내 주변 20km 이내 검색완료");
				break;
			case 4:
				text_progress.setText("내 주변 50km 이내 검색완료");
				break;
			}
			Toast.makeText(FindCarPool.this, "검색완료. find 이미지를 클릭하면 자세한 내용을 볼 수 있습니다.", Toast.LENGTH_SHORT).show();
		}
	};

	/**
	 * 검색옵션이 눌렸을 때의 이벤트
	 */
	private View.OnClickListener on_option = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			DialogRadio();
		}
	};

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	/**
	 * 변경된 정보를 지도에 표시
	 */
	@Override
	public void onLocationChanged(Location _location) {
		//맵위에 그려진 이미지들을 모두 지운다
		map.removeAllViews();

		//내 위치의 위도와 경도를 최신화 한다
		updateWithNewLocation(_location);

		double lati = _Latitude * (1E6);
		double longi = _Longitude * (1E6);

		GeoPoint pt = new GeoPoint((int)lati, (int)longi);
		controller.animateTo(pt);

		//내 위치를 나타낼 수 있는 이미지를 띄운다
		ImageView me = new ImageView(getApplicationContext());
		me.setImageResource(R.drawable.me);
		MapView.LayoutParams lp = new MapView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
				pt, MapView.LayoutParams.CENTER);
		map.addView(me, lp);

		//한번 업데이트 했으면 이제 그만, 계속하면 느려지잖어
		_Location.removeUpdates(FindCarPool.this);
	}

	@Override
	public void onProviderDisabled(String arg0) {
		updateWithNewLocation(null);
	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub

	}

	/**
	 * 좌표 값에 있는 주소의 이름을 알아내는데 사용하는 메소드
	 * @return : 지역정보
	 */
	public String get_Geocode(double latitude, double longitude){
		String _Result = "";

		Geocoder _Geocoder = new Geocoder(this);

		Iterator<Address> _Addresses;
		try {
			_Addresses = _Geocoder.getFromLocation(latitude, longitude, 10).iterator();

			if(_Addresses != null){
				while (_Addresses.hasNext()){
					Address namedLoc = _Addresses.next();
					String placeName = namedLoc.getLocality();
					String featureName = namedLoc.getFeatureName();
					String road = namedLoc.getThoroughfare();
					_Result += String.format("\n[%s][%s][%s]", placeName, featureName, road);
				}
			}
		} catch (IOException e) {
			return "Error";
		}
		return _Result;
	}

	/**
	 * 맵위에 검색결과를 아이콘으로 출력하기위한 클래스
	 * @author Chae
	 *
	 */
	private class SitesOverlay extends ItemizedOverlay<OverlayItem> {

		private List<OverlayItem> items = new ArrayList<OverlayItem>();
		private Drawable marker = null;

		public SitesOverlay(Drawable marker) {

			super(marker);
			this.marker = marker;

			items.clear();

			for(int i = 0; i < result_sub_content.size(); i++){
				double x = result_sub_content.get(i).getLatitude();
				double y = result_sub_content.get(i).getLongitude();
				GeoPoint point = new GeoPoint((int)(x * (1E6)), (int)(y  * (1E6)));
				items.add(new OverlayItem(point, result_sub_content.get(i).getStart(), null));
			}

			populate();
		}

		@Override
		protected OverlayItem createItem(int i) {
			return (items.get(i));
		}

		@Override
		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			super.draw(canvas, mapView, false);
			boundCenterBottom(marker);
		}

		/**
		 * 그림이 눌렸을 때 액티비티를 띄울 메소드
		 */
		@Override
		protected boolean onTap(int i) {
			OverlayItem layItem = items.get(i);

			//클릭된 게시물과 같은 출발지를 한꺼번에 모아서 보내준다
			String start = layItem.getTitle();
			ArrayList<Content> final_content = new ArrayList<Content>();
			ArrayList<BBSCarPoolContent> final_sub_content = new ArrayList<BBSCarPoolContent>();

			for(int j = 0; j < result_sub_content.size(); j++){
				//같은거 발견하면 리스트에 넣는다
				if(start.equals(result_sub_content.get(j).getStart())){
					Content c = new Content(result_content.get(j).getTitle(), result_content.get(j).getId());
					final_content.add(c);
					BBSCarPoolContent b = new BBSCarPoolContent(result_sub_content.get(j).getNumber(), result_sub_content.get(j).getStart(), result_sub_content.get(j).getFinish(), 
							result_sub_content.get(j).getTime(), result_sub_content.get(j).getContent(), result_sub_content.get(j).getDate(), result_sub_content.get(j).getLatitude(), 
							result_sub_content.get(j).getLongitude());
					final_sub_content.add(b);
				}
			}


			Bundle b = new Bundle();
			b.putString("ID", id);
			b.putSerializable("TITLE", final_content);
			b.putSerializable("CONTENT", final_sub_content);
			Intent intent = new Intent(FindCarPool.this, FindCarPoolResult.class);
			intent.putExtras(b);
			startActivity(intent);

			return true;
		}

		@Override
		public int size() {
			return (items.size());
		}
	}

	/**
	 * 나의 위치정보를 업데이트한다
	 * @param location
	 */
	private void updateWithNewLocation(Location location) {      
		if(location != null) {          
			_Latitude = location.getLatitude();          
			_Longitude = location.getLongitude();           
		}  
	}

	/**
	 * 검색옵션 다이얼로그
	 */
	private void DialogRadio(){
		final CharSequence[] PhoneModels = {"내 주변 2km이내", "내 주변 5km이내", "내 주변 10km이내", "내 주변 20km이내", "내 주변 50km이내"};
		AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
		alt_bld.setIcon(R.drawable.icon);
		alt_bld.setTitle("검색옵션을 선택하세요");
		alt_bld.setSingleChoiceItems(PhoneModels, -1, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int item) {
				Toast.makeText(getApplicationContext(), "검색옵션 : " + PhoneModels[item], Toast.LENGTH_SHORT).show();
				flag = item;
				dialog.cancel();
			}
		});
		AlertDialog alert = alt_bld.create();
		alert.show();
	}

}
